package com.yanzhengwu.boot.core.aop;

import com.yanzhengwu.boot.core.common.annotation.TransactionMulti;
import com.yanzhengwu.boot.core.datasource.DynamicDataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.sql.SQLException;

@Slf4j
@Aspect
@Component
public class DynamicMultiTransactionAop {


    @Autowired
    DynamicDataSource dataSourceRouting;


    @Pointcut("@annotation(com.yanzhengwu.boot.core.common.annotation.TransactionMulti)"
            + "|| @within(com.yanzhengwu.boot.core.common.annotation.TransactionMulti)"
    )
    public void annotationPointcut() {
    }


    @Around("annotationPointcut()")
    public Object roundExecute(ProceedingJoinPoint joinPoint) throws Throwable {
        log.debug("===================开始处理事务===================");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        TransactionMulti annotation = method.getAnnotation(TransactionMulti.class);
        int transactionType = annotation.transactionType();
        //开启事务
        dataSourceRouting.beginTransaction(transactionType);
        //正真执行了 方法
        Object proceed = joinPoint.proceed();
        //提交事务
        dataSourceRouting.commitTransaction();

        log.debug("===================结束处理事务===================");
        return proceed;
    }

    @AfterThrowing(pointcut = "annotationPointcut()", throwing = "e")
    public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller类抛出的异常在这边捕获
        try {
            //回滚事物
            dataSourceRouting.rollbackTransaction();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
    }

}
